﻿using PC.AzureMultiApp.Storage;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using Microsoft.WindowsAzure.Moles;
using Microsoft.WindowsAzure.StorageClient.Moles;
using Microsoft.WindowsAzure;
using PC.AzureMultiApp.Storage.Moles;
using System.Linq;
using System.Data.Services.Client.Moles;

namespace Storage.Test
{
    
    
    /// <summary>
    ///This is a test class for ApplicationDataSourceTest and is intended
    ///to contain all ApplicationDataSourceTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ApplicationDataSourceTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        private bool setConfigurationSettingCalled = false;
        private bool fromConfigurationSettingCalled = false;
        private bool createCloudTableClientCloudStorageAccountCalled = false;
        private bool createTableIfNotExistStringCalled = false;
        private bool storageContextCalled = false;
        private MStorageContext storageContext = new MStorageContext();

        public ApplicationDataSourceTest()
        {
            MCloudStorageAccount.SetConfigurationSettingPublisherActionOfStringFuncOfStringBoolean
                = (a) => { setConfigurationSettingCalled = true; };

            MCloudStorageAccount storageAccount = new MCloudStorageAccount();

            storageAccount.TableEndpointGet = () => { return new Uri("http://dummy"); };

            storageAccount.CredentialsGet = () => { return null;  };

            MCloudStorageAccount.FromConfigurationSettingString = (a) 
                => 
                {
                    fromConfigurationSettingCalled = true;
                    return storageAccount;
                };

            MCloudTableClient tableClient = new MCloudTableClient();

            MCloudStorageAccountStorageClientExtensions.CreateCloudTableClientCloudStorageAccount = (a)
                => 
                {
                    createCloudTableClientCloudStorageAccountCalled = true;
                    return tableClient; 
                };

            tableClient.CreateTableIfNotExistString = (a) => 
            {
                createTableIfNotExistStringCalled = true;
                return true;  
            };

            MStorageContext.ConstructorStringStorageCredentials 
                = (StorageContext context, string address, StorageCredentials credentials) 
                => 
                {
                    Assert.AreEqual(address, "http://dummy/");
                    Assert.IsNull(credentials);
                    storageContextCalled = true;
                    context = storageContext;
                };
        }

        #region Additional test attributes

        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            setConfigurationSettingCalled = false;
            fromConfigurationSettingCalled = false;
            createCloudTableClientCloudStorageAccountCalled = false;
            createTableIfNotExistStringCalled = false;
            storageContextCalled = false;
        }

        //
        //Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            setConfigurationSettingCalled = false;
            fromConfigurationSettingCalled = false;
            createCloudTableClientCloudStorageAccountCalled = false;
            createTableIfNotExistStringCalled = false;
            storageContextCalled = false;
        }

        #endregion


        [TestMethod()]
        [HostType("Moles")]
        public void ApplicationDataSourceConstructorTest()
        {
            ApplicationDataSource target = new ApplicationDataSource();

            Assert.IsTrue(setConfigurationSettingCalled);
            Assert.IsTrue(fromConfigurationSettingCalled);
            Assert.IsTrue(createCloudTableClientCloudStorageAccountCalled);
            Assert.IsTrue(createTableIfNotExistStringCalled);
            Assert.IsTrue(storageContextCalled);
        }

        [TestMethod()]
        [HostType("Moles")]
        public void ClearTest()
        {
            ApplicationDataSource target = new ApplicationDataSource();

            int elementToDeleteCount = 0;
            IEnumerable<AzureApplicationEntity> values = new List<AzureApplicationEntity>()
            {
               new AzureApplicationEntity(), new AzureApplicationEntity()
            };

            MStorageContext.AllInstances.ApplicationsGet = (a) =>
            {
                return values.AsQueryable<AzureApplicationEntity>();
            };

            MDataServiceContext.AllInstances.DeleteObjectObject = (context, o) 
                => 
                {
                    elementToDeleteCount = elementToDeleteCount + 1;
                } ;

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a) 
                => 
                {
                    saveCalled = true;
                    return null;  
                };

            target.Clear();

            Assert.IsTrue(elementToDeleteCount == 2);
            Assert.IsTrue(saveCalled);
        }

        [TestMethod()]
        [HostType("Moles")]
        public void Clear_ZeroElements_Test()
        {
            ApplicationDataSource target = new ApplicationDataSource();

            int elementToDeleteCount = 0;
            IEnumerable<AzureApplicationEntity> values = new List<AzureApplicationEntity>()
            {
               
            };

            MStorageContext.AllInstances.ApplicationsGet = (a) =>
            {
                return values.AsQueryable<AzureApplicationEntity>();
            };

            MDataServiceContext.AllInstances.DeleteObjectObject = (context, o)
                =>
            {
                elementToDeleteCount = elementToDeleteCount + 1;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.Clear();

            Assert.IsTrue(elementToDeleteCount == 0);
            Assert.IsTrue(saveCalled);
        }

        [TestMethod()]
        [HostType("Moles")]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Delete_ArgumentNullException_Test()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            target.Delete(null);
        }

        [TestMethod()]
        [HostType("Moles")]
        public void DeleteTest()
        {
            AzureApplicationEntity entity = new AzureApplicationEntity();

            ApplicationDataSource target = new ApplicationDataSource();

            bool deleteCalled = false;
            MDataServiceContext.AllInstances.DeleteObjectObject = (context, o)
                =>
            {
                deleteCalled = true;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.Delete(entity);

            Assert.IsTrue(deleteCalled);
            Assert.IsTrue(saveCalled);
            
        }

        [TestMethod()]
        [HostType("Moles")]
        [Ignore]
        public void GetAllTest()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            
            IEnumerable<AzureApplicationEntity> expected = new List<AzureApplicationEntity> ()
            {
               new AzureApplicationEntity(), new AzureApplicationEntity()
            };

            IEnumerable<AzureApplicationEntity> actual;

            MStorageContext.AllInstances.ApplicationsGet = (a) => 
            {
                return expected.AsQueryable<AzureApplicationEntity>(); 
            };

            actual = target.GetAll();

            Assert.IsNotNull(actual);
            Assert.IsTrue(actual.Count() == 2);
        }


        [TestMethod()]
        [HostType("Moles")]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Insert_ArgumentNullException_Test()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            target.Insert(null);
        }


        [TestMethod()]
        [HostType("Moles")]
        public void InsertTest()
        {
            ApplicationDataSource target = new ApplicationDataSource(); 
            AzureApplicationEntity entity = new AzureApplicationEntity();

            bool addCalled = false;
            MDataServiceContext.AllInstances.AddObjectStringObject = (a, b, c)
                =>
            {
                addCalled = true;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.Insert(entity);

            Assert.IsTrue(addCalled);
            Assert.IsTrue(saveCalled);            
        }

        [TestMethod()]
        [HostType("Moles")]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Update_ArgumentNullException_Test()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            target.Update(string.Empty, null);
        }


        [TestMethod()]
        [HostType("Moles")]
        public void Update_NoExists_Test()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            string uniqueId = "no exists";
            AzureApplicationEntity entity = new AzureApplicationEntity();

            IEnumerable<AzureApplicationEntity> expected = new List<AzureApplicationEntity>()
            {
               new AzureApplicationEntity() { UniqueId = "value 1" } , new AzureApplicationEntity() { UniqueId = "value 2" }
            };

            MStorageContext.AllInstances.ApplicationsGet = (a) =>
            {
                return expected.AsQueryable<AzureApplicationEntity>();
            };

            bool updateCalled = false;
            MDataServiceContext.AllInstances.UpdateObjectObject = (context, o)
                =>
            {
                updateCalled = true;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.Update(uniqueId, entity);

            Assert.IsFalse(updateCalled);
            Assert.IsFalse(saveCalled);
            
        }

        [TestMethod()]
        [HostType("Moles")]
        public void UpdateTest()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            string uniqueId = "value 1";
            AzureApplicationEntity entity = new AzureApplicationEntity();

            IEnumerable<AzureApplicationEntity> expected = new List<AzureApplicationEntity>()
            {
               new AzureApplicationEntity() { UniqueId = "value 1" } , new AzureApplicationEntity() { UniqueId = "value 2" }
            };

            MStorageContext.AllInstances.ApplicationsGet = (a) =>
            {
                return expected.AsQueryable<AzureApplicationEntity>();
            };

            bool updateCalled = false;
            MDataServiceContext.AllInstances.UpdateObjectObject = (context, o)
                =>
            {
                updateCalled = true;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.Update(uniqueId, entity);

            Assert.IsTrue(updateCalled);
            Assert.IsTrue(saveCalled);

        }

        [TestMethod()]
        [HostType("Moles")]
        public void UpdateStatusTest()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            string uniqueId = "value 1";
            string status = string.Empty; 
            AzureApplicationEntity entity = new AzureApplicationEntity();

            IEnumerable<AzureApplicationEntity> expected = new List<AzureApplicationEntity>()
            {
               new AzureApplicationEntity() { UniqueId = "value 1" } , new AzureApplicationEntity() { UniqueId = "value 2" }
            };

            MStorageContext.AllInstances.ApplicationsGet = (a) =>
            {
                return expected.AsQueryable<AzureApplicationEntity>();
            };

            bool updateCalled = false;
            MDataServiceContext.AllInstances.UpdateObjectObject = (context, o)
                =>
            {
                updateCalled = true;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.UpdateStatus(uniqueId, status);

            Assert.IsTrue(updateCalled);
            Assert.IsTrue(saveCalled);
            
        }

        [TestMethod()]
        [HostType("Moles")]
        public void UpdateStatus_NoExists_Test()
        {
            ApplicationDataSource target = new ApplicationDataSource();
            string uniqueId = "noexists";
            string status = string.Empty;
            AzureApplicationEntity entity = new AzureApplicationEntity();

            IEnumerable<AzureApplicationEntity> expected = new List<AzureApplicationEntity>()
            {
               new AzureApplicationEntity() { UniqueId = "value 1" } , new AzureApplicationEntity() { UniqueId = "value 2" }
            };

            MStorageContext.AllInstances.ApplicationsGet = (a) =>
            {
                return expected.AsQueryable<AzureApplicationEntity>();
            };

            bool updateCalled = false;
            MDataServiceContext.AllInstances.UpdateObjectObject = (context, o)
                =>
            {
                updateCalled = true;
            };

            bool saveCalled = false;
            MDataServiceContext.AllInstances.SaveChanges = (a)
                =>
            {
                saveCalled = true;
                return null;
            };

            target.UpdateStatus(uniqueId, status);

            Assert.IsFalse(updateCalled);
            Assert.IsFalse(saveCalled);

        }
    }
}
